﻿#include "ChatCenter.h"
#include "CenterService.h"
#include "Cache/OfflineCharacterData.h"
#include "Cache/OfflineCharacterDataMgr.h"
#include "Active/ActiveCharacter.h"
#include "Active/ActiveCharacterMgr.h"
#include "RelationMgr/RelationMgr.h"
#include "Camp/CampMgr.h"
#include "Team/TeamManager.h"
#include "Union/UnionMgr.h"
#include "Common/TableData/ChatChatCfg.h"

ChatCenter::ChatCenter()
{

}

ChatCenter::~ChatCenter()
{

}

void ChatCenter::onClientMessage(uint32_t actionId, RECV_PACKAGE& package, uint64_t Id /* = 0 */)
{
	UNPACK_MESSAGE_CHAR_ID(package);

	switch (actionId)
	{
	case CLIENT_TO_CENTER_ASKOFFLINEMSG:
	{
		OnAskOfflineMsgReq(charId, package);
		break;
	}
	case CLIENT_TO_CENTER_INTRVALASKOFFLINEMSG:
	{
		OnIntrvalAskOfflineMsgReq(charId, package);
		break;
	}
	default:
		break;
	}
}

void ChatCenter::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case CENTER_SERVER_PROTOCOL_CHAT_REQ:
	{
		OnServerChatReq(package);
		break;
	}
	case CENTER_SERVER_PROTOCOL_GWSYSCHATMSGNOTIFY:
	{
		OnSysChatMsgNotify(package);
		break;
	}
	default:
		break;
	}
}

bool ChatCenter::OnServerChatReq(RECV_PACKAGE &package)
{
	ProtoBuf::GWChatMsgReq chatMsgReq;
	ProtoBuf::GCChatMsgRsp chatMsgRsp;

	if (!chatMsgReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("GWChatMsgReq parse failed...");
		return false;
	}

	CharIDType charID = chatMsgReq.fromid();
	CharIDType targetID = chatMsgReq.targetid();
	ProtoBuf::CHAT_TYPE chatType = chatMsgReq.chattype();

	OfflineCharacterData *pFromOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charID);
	if (nullptr == pFromOffline)
	{
		MMOLOG_FMT_ERROR("[center] OnGCChatMsgRsp can not find offline data , charid:%llu ", charID);
		return false;
	}

	ActiveCharacter *pFromOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(charID);
	if (nullptr == pFromOnline)
	{
		MMOLOG_FMT_ERROR("[center] OnGCChatMsgRsp can not find online character data , charid:%llu ,account:%d ", charID, pFromOffline->GetUid());
		return false;
	}

	ProtoBuf::CharacterPlayerMiniInfo* playerMiniInfo = chatMsgRsp.mutable_fromplayerinfo();
	playerMiniInfo->set_playerid(charID);
	playerMiniInfo->set_playername(pFromOffline->GetCharName());
	playerMiniInfo->set_sex(pFromOffline->GetSex());
	playerMiniInfo->set_level(pFromOffline->GetLevel());
	playerMiniInfo->set_prof(pFromOffline->GetProf());

	chatMsgRsp.set_chattype(chatType);
	chatMsgRsp.set_msgtype(chatMsgReq.msgtype());
	chatMsgRsp.mutable_chatcontent()->CopyFrom(chatMsgReq.chatcontent());

	switch (chatType)
	{
	case ProtoBuf::CHAT_TYPE_WORLD:
	case ProtoBuf::CHAT_TYPE_ROOM_ENLIST: //房间招募
	case ProtoBuf::CHAT_TYPE_HORN: //大喇叭
	case ProtoBuf::CHAT_TYPE_ENLIST:	//组队喊话
	{
		SendWorldMsg(ProtoBuf::LOGIC_TO_CLIENT_CHATMSGREQ, &chatMsgRsp);
		break;
	}
	case ProtoBuf::CHAT_TYPE_CAMP: //阵营
	{
		int8_t campID = pFromOffline->GetCampID();
		SendCampMsg(ProtoBuf::LOGIC_TO_CLIENT_CHATMSGREQ, campID, &chatMsgRsp);
		break;
	}
	case ProtoBuf::CHAT_TYPE_GUILD:
	{
		SendUnionMsg(ProtoBuf::LOGIC_TO_CLIENT_CHATMSGREQ, charID, &chatMsgRsp);
		break;
	}
	case ProtoBuf::CHAT_TYPE_TEAM: //组队频道
	{
		g_GetTeamMgr()->BroadcastTeam(charID, EMODULE_ID_CHAT, ProtoBuf::LOGIC_TO_CLIENT_CHATMSGREQ, &chatMsgRsp, false, false);
		break;
	}
	case ProtoBuf::CHAT_TYPE_SYSTEM:
		break;
	/*case ProtoBuf::CHAT_TYPE_ENLIST:
	{
		int8_t campID = pFromOffline->GetCampID();
		SendEnlistMsg(ProtoBuf::LOGIC_TO_CLIENT_CHATMSGREQ, campID, &chatMsgRsp);
		break;
	}*/
	case ProtoBuf::CHAT_TYPE_PRIVATE:
	{
		//自己无法跟自己聊天
		if (charID == targetID)
		{
			chatMsgRsp.Clear();
			chatMsgRsp.set_ret(RET_CHAT_NOT_MYSELF);
			SendW2C(ProtoBuf::LOGIC_TO_CLIENT_CHATMSGREQ, charID, &chatMsgRsp);
			return false;
		}

		//判断是否可以进行私聊
		if (ValidatePrivateChat(charID, targetID))
		{
			chatMsgRsp.Clear();
			chatMsgRsp.set_ret(RET_CHAT_TARGET_IN_BLACK);
			SendW2C(ProtoBuf::LOGIC_TO_CLIENT_CHATMSGREQ, charID, &chatMsgRsp);
			return false;
		}

		//如果对方在线
		ActiveCharacter *pDstOnline = g_GetActiveCharacterMgr()->GetOnlineCharacter(targetID);
		if (nullptr == pDstOnline)
		{
			//好友可以进行离线聊天，非好友关系只能是在线聊天
			if (g_GetRelationMgr()->IsFriendRelation(charID, targetID))
			{
				SendOfflineMsg(charID, targetID, chatMsgReq.chatcontent());
				return true;
			}
			else
			{
				chatMsgRsp.Clear();
				chatMsgRsp.set_ret(RET_CHAT_TARGET_NOT_ONLINE);
				SendW2C(ProtoBuf::LOGIC_TO_CLIENT_CHATMSGREQ, charID, &chatMsgRsp);
				return false;

			}
		}
		else
		{
			chatMsgRsp.set_ret(RET_SUCCESS);
			SendW2C(ProtoBuf::LOGIC_TO_CLIENT_CHATMSGREQ, targetID, &chatMsgRsp);
		}
	}
	break;
	default:
		break;
	}
	return true;
}

bool ChatCenter::OnSysChatMsgNotify(RECV_PACKAGE &package)
{
	ProtoBuf::GWSysChatMsgNotify notifyMsg;

	if (!notifyMsg.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("GWSysChatMsgNotify parse failed...");
		return false;
	}

	ProtoBuf::GCSystemChatMsgNotify msg;
	msg.set_chattype(notifyMsg.chattype());
	msg.set_msgtype(notifyMsg.msgtype());
	msg.mutable_players()->CopyFrom(notifyMsg.players());
	msg.mutable_text()->CopyFrom(notifyMsg.text());
	msg.mutable_parmas()->CopyFrom(notifyMsg.parmas());

	switch (notifyMsg.chattype())
	{
	//case ProtoBuf::CHAT_TYPE_CAMP_RUMOR: //阵营传闻专用
	//{
	//	int8_t campID = notifyMsg.extraid();
	//	SendCampMsg(campID, &msg);
	//}
	//break;
	default:
	{
		SendWorldMsg(ProtoBuf::LOGIC_TO_CLIENT_SYSTEMCHATMSGNOTIFY, &msg);
	}
	break;
	}

	return true;
}

bool ChatCenter::OnAskOfflineMsgReq(CharIDType charID, RECV_PACKAGE &package)
{
	ProtoBuf::CWAskOfflineMsgReq askOfflineMsgReq;

	if (!askOfflineMsgReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWAskOfflineMsgReq parse failed...");
		return false;
	}

	AskOfflineMsg(charID);

	return true;
}

bool ChatCenter::OnIntrvalAskOfflineMsgReq(CharIDType charID, RECV_PACKAGE &package)
{
	ProtoBuf::CWIntrvalAskOfflineMsgReq IntrvalaskOfflineMsgReq;

	if (!IntrvalaskOfflineMsgReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWIntrvalAskOfflineMsgReq parse failed...");
		return false;
	}

	uint32_t size = IntrvalaskOfflineMsgReq.size();

	IntrvalAskOfflineMsg(charID, size);

	return true;
}

bool ChatCenter::ValidatePrivateChat(CharIDType srcID, CharIDType dstID)
{
	return g_GetRelationMgr()->IsInBlack(srcID, dstID);
}

void ChatCenter::SendOfflineMsg(CharIDType srcID, CharIDType dstID, const ::google::protobuf::RepeatedPtrField< ::ProtoBuf::ChatContentInfo >& chatContent)
{
	std::vector<ProtoBuf::ChatContentInfo> vChatContent;

	for (int i = 0; i < chatContent.size(); i++)
	{
		vChatContent.push_back(chatContent.Get(i));
	}

	PlayerMap::iterator iter = _playerMap.find(dstID);
	if (iter != _playerMap.end())
	{
		if (iter->second.msgList.size() > MAX_OFFLINE_MSG)
		{
			//删除最早的
			PrivateMsgList::iterator msgIter = iter->second.msgList.begin();
			iter->second.msgList.erase(msgIter);
		}

		OffLinePrivateMsg msg;
		msg.chatContent = vChatContent;
		msg.fromPlayerID = srcID;
		msg.sendTime = Time::Now().UnixSec();
		iter->second.msgList.push_back(msg);
	}
	else
	{
		//如果没有用户节点 创建新节点
		PlayerPrivateMsgNode playerNode;
		playerNode.playerID = dstID;
		OffLinePrivateMsg msg;
		msg.chatContent = vChatContent;
		msg.fromPlayerID = srcID;
		msg.sendTime = Time::Now().UnixSec();
		playerNode.msgList.push_back(msg);
		
		_playerMap[dstID] = playerNode;
	}
}

void ChatCenter::AskOfflineMsg(CharIDType charID)
{
	ProtoBuf::WCAskOfflineMsgRsp askOfflineMsgRsp;

	//离线私人聊天消息
	PlayerMap::iterator iter = _playerMap.find(charID);
	if (iter != _playerMap.end())
	{
		uint32_t size = iter->second.msgList.size();
		askOfflineMsgRsp.set_msgsize(size);
	}

	g_GetCenterService()->SendDataToClient(charID, EMODULE_ID_CHAT, CENTER_TO_CLIENT_ASKOFFLINEMSG, &askOfflineMsgRsp);
}

void ChatCenter::IntrvalAskOfflineMsg(CharIDType charID, uint32_t size)
{
	ProtoBuf::WCIntrvalAskOfflineMsgRsp intravlAskOfflineMsgRsp;

	//离线私人聊天消息
	PlayerMap::iterator iter = _playerMap.find(charID);
	if (iter != _playerMap.end())
	{
		uint32_t msgSize = iter->second.msgList.size();
		if (msgSize > size)
		{
			msgSize = size;
		}

		for (uint32_t i = 0; i < msgSize; i++)
		{
			ProtoBuf::OfflineMsg* offlineMsg = intravlAskOfflineMsgRsp.add_offlinemsglist();
			CharIDType chatID = iter->second.msgList[i].fromPlayerID;
			OfflineCharacterData* OfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(chatID);
			if (nullptr == OfflineCharacterData)
			{
				MMOLOG_FMT_ERROR("[center] ChatCenter::AskOfflineMsg but OfflineCharacterData is nullptr,chatID:%llu ", chatID);
				continue;
			}

			ProtoBuf::CharacterPlayerMiniInfo* playerInfo = offlineMsg->mutable_playerinfo();
			playerInfo->set_playerid(chatID);
			playerInfo->set_playername(OfflineCharacterData->GetCharName());
			playerInfo->set_sex(OfflineCharacterData->GetSex());
			playerInfo->set_level(OfflineCharacterData->GetLevel());
			playerInfo->set_prof(OfflineCharacterData->GetProf());

			for (uint32_t j = 0; j < iter->second.msgList[i].chatContent.size(); j++)
			{
				ProtoBuf::ChatContentInfo* chatContentInfo = offlineMsg->add_chatcontent();
				chatContentInfo->CopyFrom(iter->second.msgList[i].chatContent[j]);
				//offlineMsg->set_sendtime(iter->second.msgList[i].sendTime);
			}
			offlineMsg->set_sendtime(iter->second.msgList[i].sendTime);
		}

		iter->second.msgList.erase(iter->second.msgList.begin(), iter->second.msgList.begin() + msgSize);

		//如果消息为空了那么清除
		if (iter->second.msgList.size() <= 0)
		{
			_playerMap.erase(iter);
		}
	}

	g_GetCenterService()->SendDataToClient(charID, EMODULE_ID_CHAT, CENTER_TO_CLIENT_INTRVALASKOFFLINEMSG, &intravlAskOfflineMsgRsp);
}

bool ChatCenter::Init()
{
	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		MMOLOG_FMT_ERROR("[center] ChatCenter::Init....nullptr == pMessageDispatch ");
		return false;
	}
	
	pMessageDispatch->registerClientHandler(EMODULE_ID_CHAT, this);
	pMessageDispatch->registerServerHandler(EMODULE_ID_CHAT, this);

	return true;
}

bool ChatCenter::UnInit()
{
	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr != pMessageDispatch)
	{
		pMessageDispatch->unregisterClientHandler(EMODULE_ID_CHAT);
		pMessageDispatch->unregisterServerHandler(EMODULE_ID_CHAT);
	}

	return true;
}

void ChatCenter::ChatCampRumor(CharIDType charID, std::string& content)
{
	ProtoBuf::GCChatMsgRsp chatMsgRsp;
	ProtoBuf::ChatContentInfo* pContentInfo = chatMsgRsp.add_chatcontent();
	pContentInfo->set_describes(content);
	//chatMsgRsp.set_chattype(CHAT_TYPE_CAMP_RUMOR);
	chatMsgRsp.set_chattype(CHAT_TYPE_CAMP);

	SendW2C(ProtoBuf::LOGIC_TO_CLIENT_CHATMSGREQ, charID, &chatMsgRsp);
}

bool ChatCenter::ChatBackEndRumor(const std::string& content, uint32_t loopCount)
{
	ProtoBuf::GCSystemChatMsgNotify rumorMsg;
	rumorMsg.set_chattype(CHAR_TYPE_BACKEND_RUMOR);
	rumorMsg.set_content(content);
	rumorMsg.set_rumorcount(loopCount);
	return SendWorldMsg(ProtoBuf::LOGIC_TO_CLIENT_SYSTEMCHATMSGNOTIFY, &rumorMsg);
}
void ChatCenter::InitPlayerMiniInfoStruct(CharIDType playerId, ProtoBuf::CharacterPlayerMiniInfo& info)
{
	OfflineCharacterData *pOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(playerId);
	if (nullptr == pOfflineCharacterData)
	{
		MMOLOG_FMT_ERROR("[center] ChatCenter::InitOffLinePlayerMiniInfoStruct but OfflineCharacterData is nullptr,charID:%llu ", playerId);
		return;
	}

	info.set_playerid(playerId);
	info.set_playername(pOfflineCharacterData->GetCharName());
	info.set_sex(pOfflineCharacterData->GetSex());
	info.set_level(pOfflineCharacterData->GetLevel());
	info.set_prof(pOfflineCharacterData->GetProf());
	info.set_camp(pOfflineCharacterData->GetCampID());
}

void ChatCenter::InitPlayerMiniInfoStruct(const char*szPlayerName, ProtoBuf::CharacterPlayerMiniInfo& info)
{
	OfflineCharacterData *pOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacterByName(szPlayerName);
	if (nullptr == pOfflineCharacterData)
	{
		MMOLOG_FMT_ERROR("[center] ChatCenter::InitOffLinePlayerMiniInfoStruct but OfflineCharacterData is nullptr, szPlayerName:%s ", szPlayerName);
		return;
	}

	info.set_playerid(pOfflineCharacterData->GetCharID());
	info.set_playername(pOfflineCharacterData->GetCharName());
	info.set_sex(pOfflineCharacterData->GetSex());
	info.set_level(pOfflineCharacterData->GetLevel());
	info.set_prof(pOfflineCharacterData->GetProf());
	info.set_camp(pOfflineCharacterData->GetCampID());
}

bool ChatCenter::SendWorldMsg(uint16_t cmd, ProtoBufBase* msg)
{
	return g_GetCenterService()->SendDataToAllClient(EMODULE_ID_CHAT, cmd, msg);
}

bool ChatCenter::SendW2C(uint16_t cmd, CharIDType playerId, ProtoBufBase* msg)
{
	return g_GetCenterService()->SendDataToClient(playerId, EMODULE_ID_CHAT, cmd, msg);
}

bool ChatCenter::SendW2C(uint16_t cmd, SET_UINT64& playerIdList, ProtoBufBase* msg)
{
	return g_GetCenterService()->SendDataToClient(playerIdList, EMODULE_ID_CHAT, cmd, msg);
}

bool ChatCenter::SendCampMsg(uint16_t cmd, int8_t campID, ProtoBufBase* msg)
{
	SET_UINT64* campSet = const_cast<SET_UINT64*>(g_GetCampMgr()->GetCampAllMember(campID));
	if (nullptr != campSet)
	{
		SendW2C(cmd, *campSet, msg);
	}

	return true;
}

bool ChatCenter::SendEnlistMsg(uint16_t cmd, int8_t campID, ProtoBufBase* msg)
{
	SET_UINT64* campSet = const_cast<SET_UINT64*>(g_GetCampMgr()->GetCampAllMember(campID));
	if (nullptr != campSet)
	{
		SendW2C(cmd, *campSet, msg);
	}

	return true;
}

bool ChatCenter::SendUnionMsg(uint16_t cmd, CharIDType playerId, ProtoBufBase* msg)
{
	uint32_t unionId = g_GetUnionMgr()->GetCharUnionId(playerId);
	if (unionId > 0)
	{
		SET_UINT64 members;
		g_GetUnionMgr()->GetUnionAllMember(unionId, members);
		SendW2C(cmd, members, msg);
	}

	return true;
}

void ChatCenter::SendWorldBroadcastChat(BROADCAST_TYPE id, SystemChatMsgData& msgData)
{
	ProtoBuf::GCSystemChatMsgNotify msg;

	if (GetSystemChatMsg(id, msgData, msg))
	{
		SendWorldMsg(ProtoBuf::LOGIC_TO_CLIENT_SYSTEMCHATMSGNOTIFY, &msg);
	}
}

bool ChatCenter::GetSystemChatMsg(BROADCAST_TYPE id, SystemChatMsgData& msgData, GCSystemChatMsgNotify& chatMsg)
{
	const ChatChatCfgInfo *pCfg = g_GetChatChatCfgTable()->GetChatChatCfgInfo(id);
	if (nullptr == pCfg)
	{
		LogErrFmtPrint("[center] ChatManager::SendWorldBroadcastChat ... nullptr == pCfg...nBroadcastChatID:%u ", id);
		return false;
	}

	if (pCfg->chatType < CHAT_TYPE_NONE || pCfg->chatType > CHAT_TYPE_LIMIT)
	{
		LogErrFmtPrint("[center] ChatManager::SendG2WBroadcast ...pCfg chatType is error .nBroadcastChatID:%u ", id);
		return false;
	}

	chatMsg.set_chattype(CHAT_TYPE(pCfg->chatType));
	chatMsg.set_msgtype(id);


	//填充角色信息
	for (uint32_t i = 0; i < msgData.players.size(); i++)
	{
		chatMsg.add_players()->CopyFrom(msgData.players[i]);
	}

	//填充text
	for (uint32_t i = 0; i < msgData.text.size(); i++)
	{
		chatMsg.add_text(msgData.text[i]);
	}

	//填充parmas
	for (uint32_t i = 0; i < msgData.params.size(); i++)
	{
		chatMsg.add_parmas(msgData.params[i]);
	}

	return true;
}


void ChatCenter::SendBroadcastChat(BROADCAST_TYPE id, SystemChatMsgData& msgData, SET_UINT64& playerIdList)
{
	ProtoBuf::GCSystemChatMsgNotify msg;

	if (GetSystemChatMsg(id, msgData, msg))
	{
		SendW2C(ProtoBuf::LOGIC_TO_CLIENT_SYSTEMCHATMSGNOTIFY, playerIdList, &msg);
	}
}



